#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include<pthread.h>
#include"list.h"
#include"udp.h"

volatile int connect_fd;
volatile c_list head_connected;
volatile c_list head_chating;
volatile c_list head_group;

void *Get_Cmd (void *arg)
{
    char *cmd=calloc(1,64);

    while (1)
    {
        bzero(cmd,64);
       fgets(cmd,64,stdin);
       if(!strcmp(cmd,"onlinelist\n"))
       {
           show4list(head_connected);
       }

       else if(!strcmp(cmd,"chatinglist\n"))
       {
           show4_chatinglist(head_chating);
       }
       else if(!strcmp(cmd,"showgroup\n"))
        {
            showgroup(head_group);
        }
        else
        {
            printf("unkown command\n");
        }
    }


}

int main(int argc, char const *argv[])
{
   
    int fd_socket=Udp_Inti();
    if(-1==fd_socket)
    {
        printf("Udp_Inti error\n");
    }

    pthread_t thread;
    pthread_create(&thread, NULL,Get_Cmd, NULL);

    head_connected= list_init();
    head_chating= list_init();
    head_group = list_init();
    struct sockaddr_in cilentaddrmsg;
    socklen_t addrlen=sizeof(struct sockaddr_in);
    char *msg_recv=calloc(MSG_LEN,1);
    while (1)
    {
        bzero(msg_recv,MSG_LEN);
        
        bzero(&cilentaddrmsg,addrlen);
        ssize_t ret_recvfrom= recvfrom(fd_socket, msg_recv, MSG_LEN,0,
                                         (struct sockaddr *)&cilentaddrmsg, &addrlen);
            if(-1==ret_recvfrom)
            {
                perror("recvfrom error");
            }

        int ret_add2list=add2list(head_connected,connect_fd++,
                                ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));

            if(-1==ret_add2list)
            {
                printf("add to onlinelst failed\n");
            }
            if(0==ret_add2list)
            {
                // printf("This cilent already exist\n");
                connect_fd --;
            }

        if(!strcmp(msg_recv,"#offline\n"))
        {
    
           if(Del4list(head_connected,ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr)))
           {
                if(Del4_Chatinglist(head_chating,ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr)))
                {
                    printf("Delete for chating list successed\n");
                }
                
                Del4_grouplist(head_group,ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));

               printf("client ip[%s] prot[%d] offline\n",
                            inet_ntoa(cilentaddrmsg.sin_addr),ntohs(cilentaddrmsg.sin_port));

               int ret_reply=Send_Reply("offline_ok",fd_socket,
                                    ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));

                if(-1==ret_reply)
                {
                    printf("send reply failed\n");
                }

            }
            
            continue;
        }
        if(!strcmp(msg_recv,"#online\n"))
        {
            int ret=Send_Onlinelist(head_connected,fd_socket,
                                ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));
            if(-1==ret)
            {
                printf("send onlinelist failed\n");
            }
            continue;
        }

        if(!strncmp(msg_recv,"#broadcast ",11))
        {
            int Ret_broadcast=Send_Broadcast(head_connected,fd_socket,msg_recv);
            if(Ret_broadcast==-1)
            {
                printf("send broadcast failed\n");
            }
            continue;
        }
        if(!strncmp(msg_recv,"#groupadd",9))
        {
         
          int Ret_Val=group_add(head_group,msg_recv,inet_ntoa(cilentaddrmsg.sin_addr),ntohs(cilentaddrmsg.sin_port));
          if(-1==Ret_Val)
          {
              printf("group crate failed\n");
          }
          else
          {
              Send_Reply("groupadd successed\n",fd_socket,
                                    ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));
          }

            continue;
        }
        if(!strncmp(msg_recv,"#group ",7))
        {
           int Ret_Val= Send2_group(fd_socket,msg_recv,head_group);
           if(-1==Ret_Val)
           {
               printf("send to group error\n");
           }

        }
         if(!strncmp(msg_recv,"#",1))
        {
            Asking_chat(head_connected,head_chating,fd_socket,msg_recv,
                                    inet_ntoa(cilentaddrmsg.sin_addr),ntohs(cilentaddrmsg.sin_port));

            continue;
        }

        if(!strncmp(msg_recv,"@filesend ",9))
        {
             Udp_Dataswap(head_chating,fd_socket,msg_recv,
                            ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));
            usleep(2000);
             Udp_detialswap(head_chating,fd_socket,msg_recv,
                            ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));
            
        }
        
       int Ret_Swap=Udp_Dataswap(head_chating,fd_socket,msg_recv,
                            ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));
        


       if(-1==Ret_Swap)
       {
           printf("Dataswap failed\n");

            int ret_reply=Send_Reply("The client you are chating with is offline\n",fd_socket,
                                             ntohs(cilentaddrmsg.sin_port),inet_ntoa(cilentaddrmsg.sin_addr));

                if(-1==ret_reply)
                {
                    printf("send reply failed\n");
                }
       }
      
        // printf("Got msg:%s\n",msg_recv);

    
    }
    
    return 0;
}

